//
//  main.m
//  06-内存管理
//
//  Created by dllo on 16/7/12.
//  Copyright © 2016年 daming. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Man.h"
int main(int argc, const char * argv[]) {
    /***内存问题***
     * 一、内存溢出
     * 内存过多导致溢出, 导致Crash
     * 二、野指针 (过度释放)
     * 指针指向未知的区域, 就是指针指向一块被释放的区域
     *
     ***内存管理方式***
     * 1.垃圾回收机制: 只有Mac上有
     * 2.MRC: 手动管理引用计数
     * 3.ARC: 自动管理引用计数(现在常用)
     ***注意*** ARC基于MRC进行管理, 系统帮程序员添加了内存管理的内容
     *
     * retain、alloc、copy需要进行内存管理
     */
    
    /***内存管理--引用计数***
     * 有retain, alloc, copy 会对引用计数加1
     * 有release, autorelease 会对引用计数加1
     * 当对象的计数器为0的时候, 系统会调用对应的dealloc方法
     */
    // 注意: 内存管理, 你对对象操作完成后, 再进行释放
    Man *man = [[Man alloc] init];
    NSLog(@"%ld", man.retainCount);
    [man retain];
    [man release];
    NSLog(@"%ld--%@", man.retainCount, man);
    
    /*集合类型, 会对 对象进行引用计数
     *addObject 对 对象进行引用计数加1
     *removeObject 对 对象进行引用计数减1
     */
    NSMutableArray *arr = [NSMutableArray arrayWithObjects:man, nil];
    NSLog(@"向数组中添加后的引用计数 %ld", man.retainCount);
    [arr removeAllObjects];
    NSLog(@"从数组中移除后的引用计数 %ld", man.retainCount);
    /* ARC
     * strong(在ARC下使用, 强引用, 引用计数加1) weak(应用于对象类型(NSObject的子类), 弱引用, 对象被释放时, 会自动置空)
     * retain(在MRC下使用, 强引用, 引用计数加1)
     * copy(拷贝, 把对象拷贝一份, 原来的引用计数不变, 新的引用计数加1)
     * assgin(应用于简单的数据类型, 不会产生引用计数)
     */
    
    /* 协议 (三步)
     * 1.声明协议, 声明协议方法
     * 2.签订协议
     * 3.实现协议方法
     */
    
    /* 如果想实现对象的copy
     * 1.签订NSCopying协议
     * 2.实现协议方法copyWithZone
     */
    
    
    Man *man2 = [man copy];
    NSLog(@"man2 = %@", man2);
    man2.name = @"张三";
    
    man2.sexual = @"女";
    // KVC(NSObject) Key-Value-coding 键值编码, 是一种间接访问成员变量的方式
    // 只要是NSObject的子类就包含这些方法
    // valueForKey
    // valueForKeyPath
    // setValue: forKey
    // setValue: forKeyPath
    id name = [man2 valueForKey:@"name"];
    NSLog(@"%@", name);
    [man setValue:@"李四" forKey:@"name"];
    NSLog(@"%@", man.name);
    Man *gayMan = [[Man alloc] init];
    gayMan.gayBoy = man2;
    id boyName = [gayMan valueForKeyPath:@"gayBoy.name"];
    NSLog(@"++++++%@", boyName);
    [gayMan release];
    [gayMan setValue:@"李四" forKeyPath:@"gayBoy.name"]; 
    NSLog(@"%@", gayMan.gayBoy.name);
    
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];    
    [dic setValue:@"张三" forKey:@"name"];
    NSLog(@"%@", dic);
    
    NSDictionary *dic1 = [[NSDictionary alloc] initWithObjectsAndKeys:@"123456789", @"id", @"description", @"dsfd", nil];
    Man *dicMan = [[Man alloc] init];
    [dicMan setValuesForKeysWithDictionary:dic1];
    
    // 加在Build phases下的编译source下
    // 如果在ARC工程下使用MRC的文件
    // -fno-objc-arc
    // 在MRC的工程下使用ARC的文件
    // -fobjc-arc
    
    return 0;
}



